﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

using Lidgren.Library.Network;
using System.Threading;
using System.Drawing;
using BBCommon;
using System.Runtime.InteropServices;
using Business;


namespace BBBot
{
   public static class Program
   {
      #region Properties

      [DllImport("user32.dll")]
      static extern bool FlashWindow(IntPtr hwnd, bool bInvert);

      private static System.Windows.Forms.NotifyIcon notifyIconNA;

      /// <summary>
      /// Obtient ou définit le LOG
      /// </summary>
      private static NetLog Log
      {
         get
         {
            return Program.ChatApplicationBusiness.Log;
         }
         set
         {
            Program.ChatApplicationBusiness.Log = value;
         }
      }
      private static NetAppConfiguration Config { get { return Program.ChatApplicationBusiness.Config; } }

      public static BBBotBusiness BBBotBusiness;

      public static ChatForm MainForm;
      private static ChatApplication _chatApplicationBusiness;
      /// <summary>
      /// Permet d'utiliser l'application de CHAT
      /// </summary>
      public static ChatApplication ChatApplicationBusiness
      {
         get
         {
            if (Program._chatApplicationBusiness == null)
            {
               Program._chatApplicationBusiness = new ChatApplication();
               Program._chatApplicationBusiness.SendingMessage += new ChatApplication.SendingMessageEvent(_chatApplicationBusiness_SendingMessage);
            }
            
            return Program._chatApplicationBusiness;
         }
      }      
      
      public static Configuration AppConfig;
      /// <summary>
      /// Obtient ou définit le client
      /// </summary>
      public static NetClient Client
      {
         get
         {
            return Program.ChatApplicationBusiness.Client;
         }
         set
         {
            Program.ChatApplicationBusiness.Client = value;
         }
      }

      public static event EventHandler HiddenStateChanged;
      private static bool _currently_hidden;
      public static bool IsAppHidden
      {
         get { return _currently_hidden; }
         set
         {
            _currently_hidden = value;
            HiddenStateChanged(null, null);
         }
      }
      /// <summary>
      /// Obtient/Définit la liste des utilisateurs
      /// </summary>
      private static PlayerList PList
      {
         get
         {
            return Program.ChatApplicationBusiness.PList;
         }
         set
         {
            Program.ChatApplicationBusiness.PList = value;
         }
      }

      #endregion

      #region Methods


      internal static void Knock(string str, BBConversation conversation)
      {
         Program.ChatApplicationBusiness.Knock(str, conversation);
      }

      internal static void Coffee(string str, BBConversation conversation)
      {
         Program.ChatApplicationBusiness.Coffee(str, conversation);
      }

      internal static void Eat(string str, BBConversation conversation)
      {
         Program.ChatApplicationBusiness.Eat(str, conversation);
      }

      internal static BBConversation StartPrivateConversation(List<string> str)
      {
         return Program.ChatApplicationBusiness.StartPrivateConversation(str);
      }

      internal static void JoinConversation(BBConversation conversation, string player)
      {
         Program.ChatApplicationBusiness.JoinConversation(conversation, player);
      }

      internal static void LeaveConversation(BBConversation BBConversation, string p)
      {
         Program.ChatApplicationBusiness.LeaveConversation(BBConversation, p);
      }

      internal static void Shoot(string str)
      {
         Program.ChatApplicationBusiness.Shoot(str);
      }

      internal static void PrivateMessage(BBConversation bBConversation, string p, string p_3)
      {
         Program.ChatApplicationBusiness.PrivateMessage(bBConversation, p, p_3);
      }

      internal static void Entered(string p)
      {
         Program.ChatApplicationBusiness.Entered(p);
      }

      internal static void ShootResponse(ShootResponseDesc.Response response, string p)
      {
         Program.ChatApplicationBusiness.ShootResponse(response, p);
      }

      //<summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         //PList = new PlayerList();
         MainForm = new ChatForm();
         AppConfig = new Configuration();
         IsAppHidden = AppConfig.RunMinimized;

         // Create a configuration for the client
         Program.ChatApplicationBusiness.Config = new NetAppConfiguration("BBTcpTest");

         Program.BBBotBusiness = new BBBotBusiness(Program.ChatApplicationBusiness);

         // enable encryption; this key was generated using the 'GenerateEncryptionKeys' application
         Config.EnableEncryption(
              "AQABwV1rQ1NDWzkkhUsYtMiRGjyxSn/zI13tros2RlXHlW6PA7Cvw2nOyMhDmweM+" +
              "T/+FWzssAWLh8qd+YHaMCCFskVdaZfRzquZlNOs9mX/vtxkLrXgBUaJQD/XOuBeJF" +
              "o3RfAKA4uhrEr7Bk1iB3zJQW1bSHK7KmmEWzMErk6iA7c=", null);

         Log = new NetLog();
         Log.IgnoreTypes = NetLogEntryTypes.Verbose; //  Verbose;
         Log.IsOutputToFileEnabled = false;

         Log.OutputFileName = "clientlog.html";

         // uncomment this if you want to start multiple instances of this process on the same computer
         //Log.OutputFileName = "clientlog" + System.Diagnostics.Process.GetCurrentProcess().Id + ".html";

         //Log.LogEvent += new EventHandler<NetLogEventArgs>(Log_LogEvent);

         Client = new NetClient(Config, Log);
         Client.StatusChanged += new EventHandler<NetStatusEventArgs>(Client_StatusChanged);

         Application.Idle += new EventHandler(ApplicationLoop);
         //MainForm.TypingStateChanged += new EventHandler<ChatForm.TypingEvent>(MainForm_TypingStateChanged);

         CreateNotificationIcon();
         Application.Run(MainForm);

         if (Client != null)
            Client.Shutdown("Application exiting");

         if (notifyIconNA != null)
            notifyIconNA.Visible = false;
      }

      #endregion

      #region Events

      static void Client_StatusChanged(object sender, NetStatusEventArgs e)
      {
         Log.Info(e.Connection + ": " + e.Connection.Status + " - " + e.Reason);

         // If just connected, begin login procedure
         if (e.Connection.Status == NetConnectionStatus.Connected)
         {            
            Program.ChatApplicationBusiness.AskLogin(MainForm.Player, BBMessage.Version);            
         }
         // If connection drops, inform user and get back to the login form
         else if (e.Connection.Status == NetConnectionStatus.Disconnected)
         {
            try // The following fails if application is exiting
            {
               PList = new PlayerList();
               Program.ChatApplicationBusiness.OutputSystemText("Disconnected ! Reason : " + e.Reason, null);
               MainForm.Connect();
            }
            catch { }
         }

      }

      static void ApplicationLoop(object sender, EventArgs e)
      {

         while (Win32.AppStillIdle)
         {
            if (Client != null)
            {
               // call heartbeat as often as possible; this sends queued packets,
               // keepalives and acknowledges etc.
               Client.Heartbeat();

               NetMessage msg;
               // read a packet if available
               while ((msg = Client.ReadMessage()) != null)
                  Program.ChatApplicationBusiness.HandleMessage(msg);

               Thread.Sleep(1); // don't hog the cpu
            }
         }
      }

      static void MainForm_TypingStateChanged(object sender, ChatForm.TypingEvent e)
      {
         BBConversation convers = sender as BBConversation;
         // Create istyping message
         BBMessage msg = new BBMessage();
         msg.MsgTypingMsg(e.isTyping);
         msg.Conversation = convers;

         // Send it.
         Client.SendMessage(msg.GetNetMessage(), NetChannel.ReliableUnordered);
      }

      static void CreateNotificationIcon()
      {
         // Initialize Notification Area Icon
         notifyIconNA = new System.Windows.Forms.NotifyIcon();
         notifyIconNA.Icon = MainForm.Icon;
         notifyIconNA.Text = "BB Communicator";

         notifyIconNA.Visible = true;
         notifyIconNA.MouseClick += new System.Windows.Forms.MouseEventHandler(NA_MouseClick);

         MainForm.SizeChanged += new EventHandler(MainForm_SizeChanged);
      }

      static void NA_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
      {
         if (e.Button == System.Windows.Forms.MouseButtons.Left)
         {
            IsAppHidden = false;
         }
      }

      static void MainForm_SizeChanged(object sender, EventArgs e)
      {
         notifyIconNA.Icon = MainForm.Icon;
      }

      #endregion

      #region Tools

      static void ShowInfoBalloon(string title, string content, System.Windows.Forms.ToolTipIcon icon)
      {
         if (!MainForm.ContainsFocus)
            notifyIconNA.ShowBalloonTip(500, title, content, icon);
         NotifyMessage();
      }

      public static void NotifyMessage()
      {
         if (!MainForm.ContainsFocus)
         {
            FlashWindow(MainForm.Handle, true);
         }
         //if (MainForm.Visible == false)
            //notifyIconNA.Icon = Resource1.Mail;
      }

      #endregion

      #region Handlers

      static void _chatApplicationBusiness_SendingMessage(BBMessage message)
      {
         Program.BBBotBusiness.CatchLetter(message, message.Message);
      }

      #endregion

   }
}
